<?php
/**
 * 图片上传/操作类
 * $Id$
 */

class image {
	private $error_message = ''
	private $image_dir = '';
	private $bgcolor = '';
	private $allow_file_types = array('GIF','JPG','JEPG','PNG','BMP','SWF');
	private $type_mapping = array(1 => 'image/gif', 2 => 'image/jpeg', 3 => 'image/png');

	/**
	 * 构造函数
	 */
	public function __construct($image_dir, $bgcolor = '') {
		if ($bcolor) {
			$this->bgcolor = $bgcolor;
		} else {
			$this->bgcolor = '#FFFFFF';
		}
		$this->image_dir = $image_dir;
	}

	/**
	 * 图片上传处理
	 */
	public function upload_image($image_dir, $allow_file_types = array(), $upload, $dir = '', $img_name = '') {
		if (empty($dir)) {
			$dir = date('Ym');
			$dir = $this->images_dir . $dir;
		}

		if ($img_name) {
			$img_name = $dir . '/' . $img_name;
		} else {
			$img_name = $this->unique_name($dir);
			$img_name = $dir . $img_name . $this->get_file_type($upload['name']);
		}

		$allow_file_types = (!empty($allow_file_types)) ? $allow_file_types : $this->allow_file_types;

		/* 如果目录不存在则创建它*/
		if (!file_exists($dir)) {
			if (!make_dir($dir)) {
				$this->error_msg = '传见文件错误:' . $dir . '为只读';
				return false;
			}
		}

		if (!$this->check_img_type($upload['type'], $img_name, $allow_file_types)) {
			$this->error_msg = '不能检查图片类型！';
			return false;
		}

		if (!this->move_file($upload, $img_name) {
			$this->error_msg = '上传文件失败！';
		}
	}

	/**
	 * 创建缩略图
	 */
	public function make_thumb($img, $thumb_width = 0, $thumb_height = 0, $path = '', $bgcolor = '') {
		$gd = $this->gd_version();
		if ($gd == 0) {
			$this->error_msg = '没有安装GD模块！';
			return false;
		}

		if ($thumb_width == 0 && $thumb_height == 0) {
			return false;
		}

		/* 检查原始文件是否存在以及获取文件信息*/
		$org_info = @getimagesize($img);
		if (!$org_info) {
			$this->error_msg = '文件不存在！';
			return false;
		}

		if (!this->check_img_function($org_info[2])) {
			$this->error_msg = '不存在当前图片类型的GD处理函数。';
			return false;
		}

		$img_org = $this->img_resource($img, $org_info[2]);
		/* 原始图片尺寸比例*/
		$scale_org = $org_info[0] / $org_info[1];
		/* 如果宽高有一个为0，根据比例计算尺寸*/
		if ($thumb_width == 0) {
			$thumb_widht = $thumb_height * $scale_org;
		}
		if ($thumb_height == 0) {
			$thumb_height = $thumb_widht / $scale_org;
		}

		/* 创建缩略图的标示符*/
		if ($gd ==2) {
			$img_thumb = imagecreatetruecolor($thumb_widht, $thumb_height);
		} else {
			$img_thumb = imagecreate($thumb_widht, $thumb_height);
		}

		if (empty($bgcolor)) {
			$bgcolor = $this->bgcolor;
		}
		$bgcolor = trim($bgcolor, '#');
		sscanf($bgcolor, "%2x%2x%2x", $red, $green, $blue);
		$clr = imagecolorallocate($img_thumb, $red, $green, $blue);
		/* 着色*/
		imagefilledrectangle($img_thumb, 0, 0, $thumb_width, $thumb_height, $clr);

		if ($org_info[0] / $thumb_width > $org_info[1] / $thumb_height) {
			$lessen_width  = $thumb_width;
			$lessen_height  = $thumb_width / $scale_org;
		} else {
			/* 原始图片比较高，则以高度为准 */
			$lessen_width  = $thumb_height * $scale_org;
			$lessen_height = $thumb_height;
		}

		$dst_x = ($thumb_width  - $lessen_width)  / 2;
		$dst_y = ($thumb_height - $lessen_height) / 2;

		/* 将原始图片进行缩放处理 */
		if ($gd == 2) {
			imagecopyresampled($img_thumb, $img_org, $dst_x, $dst_y, 0, 0, $lessen_width, $lessen_height, $org_info[0], $org_info[1]);
		} else {
			imagecopyresized($img_thumb, $img_org, $dst_x, $dst_y, 0, 0, $lessen_width, $lessen_height, $org_info[0], $org_info[1]);
		}

		/* 创建当月目录 */
		if (empty($path)) {
			$dir = ROOT_PATH . $this->images_dir . '/' . date('Ym').'/';
		} else {
			$dir = $path;
		}


		/* 如果目标目录不存在，则创建它 */
		if (!file_exists($dir)) {
			if (!make_dir($dir)) {
				/* 创建目录失败 */
				$this->error_msg  = '创建目录失败！';
				return false;
			}
		}

		/* 如果文件名为空，生成不重名随机文件名 */
		$filename = $this->unique_name($dir);

		/* 生成文件 */
		if (function_exists('imagejpeg')) {
			$filename .= '.jpg';
			imagejpeg($img_thumb, $dir . $filename);
		} elseif (function_exists('imagegif')) {
			$filename .= '.gif';
			imagegif($img_thumb, $dir . $filename);
		} elseif (function_exists('imagepng')) {
			$filename .= '.png';
			imagepng($img_thumb, $dir . $filename);
		} else {
			$this->error_msg = '生成文件错误!';
			return false;
		}

		imagedestroy($img_thumb);
		imagedestroy($img_org);

		//确认文件是否生成
		if (file_exists($dir . $filename)) {
			return str_replace(ROOT_PATH, '', $dir) . $filename;
		} else {
			$this->error_msg = '文件没有被生成！';
			return false;
		}
	}

	/**
	 * 为图片增加水印
	 *
	 * @access      public
	 * @param       string      filename            原始图片文件名，包含完整路径
	 * @param       string      target_file         需要加水印的图片文件名，包含完整路径。如果为空则覆盖源文件
	 * @param       string      $watermark          水印完整路径
	 * @param       int         $watermark_place    水印位置代码
	 * @return      mix         如果成功则返回文件路径，否则返回false
	 */
	public function add_watermark($filename, $target_file='', $watermark='', $watermark_place='', $watermark_alpha = 0.65) {
		// 是否安装了GD
		$gd = $this->gd_version();
		if ($gd == 0) {
			$this->error_msg = '没有GD库！';
			return false;
		}

		// 文件是否存在
		if ((!file_exists($filename)) || (!is_file($filename))) {
			$this->error_msg  = '文件不存在！';
			return false;
		}

		/* 如果水印的位置为0，则返回原图 */
		if ($watermark_place == 0 || empty($watermark)) {
			return str_replace(ROOT_PATH, '', str_replace('\\', '/', realpath($filename)));
		}

		if (!$this->validate_image($watermark)) {
			/* 已经记录了错误信息 */
			return false;
		}

		// 获得水印文件以及源文件的信息
		$watermark_info     = @getimagesize($watermark);
		$watermark_handle   = $this->img_resource($watermark, $watermark_info[2]);

		if (!$watermark_handle) {
			$this->error_msg = '添加水印错误！';
			return false;
		}

		// 根据文件类型获得原始图片的操作句柄
		$source_info    = @getimagesize($filename);
		$source_handle  = $this->img_resource($filename, $source_info[2]);
		if (!$source_handle) {
			$this->error_msg = '获得文件句柄错误！';
			return false;
		}

		// 根据系统设置获得水印的位置
		switch ($watermark_place) {
			case '1':
				$x = 0;
				$y = 0;
				break;
			case '2':
				$x = $source_info[0] - $watermark_info[0];
				$y = 0;
				break;
			case '4':
				$x = 0;
				$y = $source_info[1] - $watermark_info[1];
				break;
			case '5':
				$x = $source_info[0] - $watermark_info[0];
				$y = $source_info[1] - $watermark_info[1];
				break;
			default:
				$x = $source_info[0]/2 - $watermark_info[0]/2;
				$y = $source_info[1]/2 - $watermark_info[1]/2;
		}

		if (strpos(strtolower($watermark_info['mime']), 'png') !== false) {
			imageAlphaBlending($watermark_handle, true);
			imagecopy($source_handle, $watermark_handle, $x, $y, 0, 0,$watermark_info[0], $watermark_info[1]);
		} else {
			imagecopymerge($source_handle, $watermark_handle, $x, $y, 0, 0,$watermark_info[0], $watermark_info[1], $watermark_alpha);
		}
		$target = empty($target_file) ? $filename : $target_file;

		switch ($source_info[2]) {
			case 'image/gif':
			case 1:
				imagegif($source_handle,  $target);
				break;

			case 'image/pjpeg':
			case 'image/jpeg':
			case 2:
				imagejpeg($source_handle, $target);
				break;

			case 'image/x-png':
			case 'image/png':
			case 3:
				imagepng($source_handle,  $target);
				break;

			default:
				$this->error_msg = $GLOBALS['_LANG']['creating_failure'];
				$this->error_no = ERR_NO_GD;

				return false;
		}

		imagedestroy($source_handle);

		$path = realpath($target);
		if ($path) {
			return str_replace(ROOT_PATH, '', str_replace('\\', '/', $path));
		} else {
			$this->error_msg = '写入失败！';
			return false;
		}
	}

	/**
	 * 检查水印图片是否合法
	 */
	public function validate_image($path) {
		if (empty($path)) {
			$this->error_msg = '文件路径不存在';
			return false;
		}

		/* 文件是否存在*/
		if (!file_exists($path)) {
			$this->error_msg = '文件不存在';
			return false;
		}

		/* 获得文件以及文件源的信息*/
		$image_info = @getimagesize($path);

		if (!image_info) {
			$this->error_msg = '不可用的文件类型';
			return false;
		}

		/* 检查处理函数是否存在*/
		if (!$this->check_img_function($image_info[2])) {
			$this->error_img = '不支持的类型';
			return false;
		}
		return true;
	}

	/**
	 * 返回错误信息
	 */
	public function error_msg() {
		return $this->error_msg;
	}

	/**
	 * 检查图片类型
	 */
	public function check_img_type($img_type) {
		return in_array($img_type, array('image/pjpeg', 'image/x-png', 'image/png', 'image/gif', 'image/jpeg'));
	}

	/**
	 * 检查图片处理能力
	 */
	public function check_img_function($img_type) {
		switch ($img_type) {
			case  'image/gif':
			case 1:
				return function_exists('imagecreatefromgif');
				break;
			case 'image/pjpeg':
			case 'image/jpeg':
			case 2:
				return function_exists('imagecreatefromjepg');
				break;
			case 'image/x-png':
			case 'image/png':
			case 3:
				return function_exists('imagecreatefrompng');
				break;
			default:
				return false;
		}
	}

	/**
	 * 生成随机数字
	 */
	public function random_filename() {
		str = '';
		for ($i = 0; $i < 9; $i++) {
			$str .= mt_rand(0, 9);
		}
		return uniqid() . $str;
	}

	/**
	 * 生成指定目录下不重名的文件名
	 */
	public function unique_name($dir) {
		$file_name = $this->random_filename();
		$exts = array('.jpg', '.gif', '.png');
		foreach ($exts as $ext) {
			if (file_exists($dir . $file_name . $ext)) {
				return false;
			}
		}
		return $file_name;
	}

	/**
	 * 返回文件后缀名
	 */
	public function get_filetype($path) {
		$pos = strrpos($path, '.');
		if ($pos !== false) {
			return substr($path, $pos);
		} else {
			return false;
		}
	}

	 /**
	 * 根据来源文件的文件类型创建一个图像操作的标识符
	 *
	 * @access  public
	 * @param   string      $img_file   图片文件的路径
	 * @param   string      $mime_type  图片文件的文件类型
	 * @return  resource    如果成功则返回图像操作标志符，反之则返回错误代码
	 */
	function img_resource($img_file, $mime_type) {
		switch ($mime_type) {
			case 1:
			case 'image/gif':
				$res = imagecreatefromgif($img_file);
				break;

			case 2:
			case 'image/pjpeg':
			case 'image/jpeg':
				$res = imagecreatefromjpeg($img_file);
				break;

			case 3:
			case 'image/x-png':
			case 'image/png':
				$res = imagecreatefrompng($img_file);
				break;

			default:
				return false;
		}
		return $res;
	}

	/**
	 * 获得服务器上的 GD 版本
	 *
	 * @access      public
	 * @return      int         可能的值为0，1，2
	 */
	function gd_version() {
		static $version = -1;

		if ($version >= 0) {
			return $version;
		}

		if (!extension_loaded('gd')) {
			$version = 0;
		} else {
			// 尝试使用gd_info函数
			if (PHP_VERSION >= '4.3') {
				if (function_exists('gd_info')) {
					$ver_info = gd_info();
					preg_match('/\d/', $ver_info['GD Version'], $match);
					$version = $match[0];
				} else {
					if (function_exists('imagecreatetruecolor')) {
						$version = 2;
					} elseif (function_exists('imagecreate')) {
						$version = 1;
					}
				}
			} else {
				if (preg_match('/phpinfo/', ini_get('disable_functions'))) {
					/* 如果phpinfo被禁用，无法确定gd版本 */
					$version = 1;
				} else {
				  // 使用phpinfo函数
				   ob_start();
				   phpinfo(8);
				   $info = ob_get_contents();
				   ob_end_clean();
				   $info = stristr($info, 'gd version');
				   preg_match('/\d/', $info, $match);
				   $version = $match[0];
				}
			 }
		}
		return $version;
	 }

	/**
	 *
	 *
	 * @access  public
	 * @param
	 *
	 * @return void
	 */
	function move_file($upload, $target) {
		if (isset($upload['error']) && $upload['error'] > 0) {
			return false;
		}

		if (!move_upload_file($upload['tmp_name'], $target)) {
			return false;
		}
		return true;
	}
}
